package com.example.myapplication.utils

import android.app.ActivityManager
import android.content.Context
import android.util.Log
import java.lang.ref.WeakReference
import kotlin.math.ln
import kotlin.math.pow

/**
 * 内存管理工具类
 */
object MemoryUtils {
    
    private const val TAG = "MemoryUtils"
    private val memoryCache = mutableMapOf<String, WeakReference<Any>>()
    
    /**
     * 内存信息数据类
     */
    data class MemoryInfo(
        val totalMemory: Long,
        val availableMemory: Long,
        val usedMemory: Long,
        val maxMemory: Long,
        val isLowMemory: Boolean
    )
    
    /**
     * 获取应用内存信息
     */
    fun getMemoryInfo(context: Context): MemoryInfo {
        val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val memoryInfo = ActivityManager.MemoryInfo()
        activityManager.getMemoryInfo(memoryInfo)
        
        val runtime = Runtime.getRuntime()
        
        return MemoryInfo(
            totalMemory = memoryInfo.totalMem,
            availableMemory = memoryInfo.availMem,
            usedMemory = runtime.totalMemory() - runtime.freeMemory(),
            maxMemory = runtime.maxMemory(),
            isLowMemory = memoryInfo.lowMemory
        )
    }
    
    /**
     * 检查是否内存不足
     */
    fun isLowMemory(context: Context): Boolean {
        return try {
            getMemoryInfo(context).isLowMemory
        } catch (e: Exception) {
            Log.e(TAG, "检查内存状态失败", e)
            false
        }
    }
    
    /**
     * 强制垃圾回收
     */
    fun forceGC() {
        try {
            System.gc()
            System.runFinalization()
            Log.d(TAG, "垃圾回收完成")
        } catch (e: Exception) {
            Log.e(TAG, "垃圾回收失败", e)
        }
    }
    
    /**
     * 清理内存缓存
     */
    fun clearMemoryCache() {
        synchronized(memoryCache) {
            val beforeSize = memoryCache.size
            memoryCache.clear()
            Log.d(TAG, "清理内存缓存: $beforeSize 项")
        }
    }
    
    /**
     * 添加到内存缓存
     */
    fun <T> putToCache(key: String, value: T) {
        synchronized(memoryCache) {
            memoryCache[key] = WeakReference(value)
        }
    }
    
    /**
     * 从内存缓存获取
     */
    @Suppress("UNCHECKED_CAST")
    fun <T> getFromCache(key: String): T? {
        synchronized(memoryCache) {
            val ref = memoryCache[key]
            return ref?.get() as? T
        }
    }
    
    /**
     * 清理过期的弱引用
     */
    fun cleanupWeakReferences() {
        synchronized(memoryCache) {
            val iterator = memoryCache.iterator()
            var removed = 0
            while (iterator.hasNext()) {
                val entry = iterator.next()
                if (entry.value.get() == null) {
                    iterator.remove()
                    removed++
                }
            }
            if (removed > 0) {
                Log.d(TAG, "清理过期弱引用: $removed 项")
            }
        }
    }
    
    /**
     * 打印内存使用情况
     */
    fun logMemoryUsage(context: Context, tag: String = TAG) {
        try {
            val info = getMemoryInfo(context)
            Log.d(tag, """
                内存使用情况:
                总内存: ${formatBytes(info.totalMemory)}
                可用内存: ${formatBytes(info.availableMemory)}
                已用内存: ${formatBytes(info.usedMemory)}
                最大内存: ${formatBytes(info.maxMemory)}
                内存不足: ${info.isLowMemory}
                内存使用率: ${String.format("%.1f", info.usedMemory * 100.0 / info.maxMemory)}%
            """.trimIndent())
        } catch (e: Exception) {
            Log.e(tag, "记录内存使用情况失败", e)
        }
    }
    
    /**
     * 格式化字节数
     */
    private fun formatBytes(bytes: Long): String {
        return try {
            val unit = 1024
            if (bytes < unit) return "$bytes B"
            
            val exp = (ln(bytes.toDouble()) / ln(unit.toDouble())).toInt()
            val pre = "KMGTPE"[exp - 1]
            String.format("%.1f %sB", bytes / unit.toDouble().pow(exp.toDouble()), pre)
        } catch (e: Exception) {
            "$bytes B"
        }
    }
}